module omicron_tb();

reg rst_n;
reg clk_in;
wire [7:0] leds;

// INSTRUCTION_FETCH
wire [15:0] if_curr_inst;
wire [6:0]  m_branch_addr;
wire        m_branch_en;
wire [6:0]  if_next_addr;

// INSTRUCTION_DECODE
wire        wb_reg_wea;
wire [15:0] wb_reg_wdata;
wire [2:0]  wb_reg_waddr;
wire [3:0]  id_opcode;          // [15:12]
wire [6:0]  id_next_addr;
wire [15:0] id_register1_data;
wire [15:0] id_register2_data;
wire [6:0]  id_sign_ext_addr;   // [6:0]
wire [2:0]  id_dest_reg_addr;   // [8:6]

// EXECUTE
wire [3:0]  cu_alu_opcode;
wire        cu_alu_sel_b;
wire [6:0]  ex_sign_ext_next_addr;
wire        ex_alu_z;
wire [15:0] ex_alu_result;
wire [15:0] ex_register2_data;
wire [2:0]  ex_reg_waddr;

// MEMORY
wire        cu_dm_wea;
wire [1:0]  cu_branch;
wire [15:0] m_alu_result;
wire [15:0] m_dm_dout;
wire [2:0]  m_reg_waddr;

// WRITE_BACK
wire        cu_reg_data_loc;
wire        cu_reg_load;

// INSTRUCTION_FETCH
assign if_curr_inst[15:0]         = DUT.i_omicron.i_data_path.i_instruction_fetch.if_curr_inst[15:0];
assign m_branch_addr[6:0]         = DUT.i_omicron.i_data_path.i_instruction_fetch.m_branch_addr[6:0];
assign m_branch_en                = DUT.i_omicron.i_data_path.i_instruction_fetch.m_branch_en;
assign if_next_addr               = DUT.i_omicron.i_data_path.i_instruction_fetch.if_next_addr[6:0];

// INSTRUCTION_DECODE
assign wb_reg_wea                 = DUT.i_omicron.i_data_path.i_instruction_decode.wb_reg_wea;
assign wb_reg_wdata[15:0]         = DUT.i_omicron.i_data_path.i_instruction_decode.wb_reg_wdata[15:0];
assign wb_reg_waddr[2:0]          = DUT.i_omicron.i_data_path.i_instruction_decode.wb_reg_waddr[2:0];
assign id_opcode[3:0]             = DUT.i_omicron.i_data_path.i_instruction_decode.id_opcode[3:0];
assign id_next_addr[6:0]          = DUT.i_omicron.i_data_path.i_instruction_decode.id_next_addr[6:0];
assign id_register1_data[15:0]    = DUT.i_omicron.i_data_path.i_instruction_decode.id_register1_data[15:0];
assign id_register2_data[15:0]    = DUT.i_omicron.i_data_path.i_instruction_decode.id_register2_data[15:0];
assign id_sign_ext_addr[6:0]      = DUT.i_omicron.i_data_path.i_instruction_decode.id_sign_ext_addr[6:0];
assign id_dest_reg_addr[2:0]      = DUT.i_omicron.i_data_path.i_instruction_decode.id_dest_reg_addr[2:0];

// EXECUTE
assign cu_alu_opcode[3:0]         = DUT.i_omicron.i_data_path.i_execute.cu_alu_opcode[3:0];
assign cu_alu_sel_b               = DUT.i_omicron.i_data_path.i_execute.cu_alu_sel_b;
assign ex_sign_ext_next_addr[6:0] = DUT.i_omicron.i_data_path.i_execute.ex_sign_ext_next_addr[6:0];
assign ex_alu_z                   = DUT.i_omicron.i_data_path.i_execute.ex_alu_z;
assign ex_alu_result[15:0]        = DUT.i_omicron.i_data_path.i_execute.ex_alu_result[15:0];
assign ex_register2_data[15:0]    = DUT.i_omicron.i_data_path.i_execute.ex_register2_data[15:0];
assign ex_reg_waddr[2:0]          = DUT.i_omicron.i_data_path.i_execute.ex_reg_waddr[2:0];

// MEMORY
assign cu_dm_wea                  = DUT.i_omicron.i_data_path.i_memory.cu_dm_wea;
assign cu_branch[1:0]             = DUT.i_omicron.i_data_path.i_memory.cu_branch[1:0];
assign m_alu_result[15:0]         = DUT.i_omicron.i_data_path.i_memory.m_alu_result[15:0];
assign m_dm_dout[15:0]            = DUT.i_omicron.i_data_path.i_memory.m_dm_dout[15:0];
assign m_reg_waddr[2:0]           = DUT.i_omicron.i_data_path.i_memory.m_reg_waddr[2:0];

// WRITE_BACK
assign cu_reg_data_loc            = DUT.i_omicron.i_data_path.i_write_back.cu_reg_data_loc;
assign cu_reg_load                = DUT.i_omicron.i_data_path.i_write_back.cu_reg_load;

initial begin
  rst_n = 0;
  clk_in = 0;
  #100 rst_n = 1;

  forever #20 clk_in = ~clk_in;

end


omicron_top DUT (
  .rst_n(rst_n),
  .clk_in(clk_in),
  .leds(leds[7:0])
);

endmodule
